#include "numuCC1P1PiAnalysis.hxx"

numuCC1P1PiAnalysis::numuCC1P1PiAnalysis(AnalysisAlgorithm* ana) : baseAnalysis(ana)
{
    // Minimum accum level to save event into the output tree
    SetMinAccumCutLevelToSave(ND::params().GetParameterI("numuCC1P1PiAnalysis.MinAccumLevelToSave"));
    
    // Create a numuCCAnalysis passing this analysis to the constructor. In that way the same managers are used
    _numuCCAnalysis = new numuCCAnalysis(this);
    
    //use it when new version of highland2 is available
    //UseAnalysis(_numuCCAnalysis);
    
    // Add the package version
    ND::versioning().AddPackage("numuCC1P1PiAnalysis", anaUtils::GetSoftwareVersionFromPath((std::string)getenv("NUMUCC1P1PIANALYSISROOT")));
}

void numuCC1P1PiAnalysis::DefineSelections()
{
    sel().AddSelection("kTrackerNumuCC1P1Pi", "inclusive numuCC1P1Pi selection",  new numuCC1P1PiSelection(1));
}

bool numuCC1P1PiAnalysis::Process()
{
    //------ This function is called for each bunch and each toy experiment  ----------
    bool passed = sel().GetSelection("kTrackerNumuCC1P1Pi")->Apply(*_event,*_cc1P1Pi_box);
    
    return passed;
}

void numuCC1P1PiAnalysis::DefineMicroTrees(bool addBase)
{
    // -------- Add variables to the analysis tree ----------------------
    
    // Variables from the numuCCAnalysis analysis (including the ones in baseAnalysis by default, otherwise addBase should be false
    if (addBase) _numuCCAnalysis->DefineMicroTrees(addBase);
    
    //--- proton candidate truth variables -------
    AddVarF(output(),selp_truemom, "");              // true proton momentum
    AddVar4VF(output(),selp_truedir, ""); // true proton direction
    AddVarI(output(),selp_pdg,"");
    
    // --- proton candidate recon variables -----
    AddToyVarI(output(),selp_NDOF,      "");
    AddToyVarF(output(),selp_Chi2,      "");
    AddToyVarF(output(),selp_mom,      "");
    AddVar3VF(output(),selp_dir, "");
    AddVarVI(output(),selp_tpc_nhits, "", selp_ntpcs);
    AddVarVF(output(), selp_tpc_charge,"", selp_ntpcs);
    AddVar4VF(output(),selp_endpos, "");
    AddVarVI(output(),selp_fgd_det, "" , selp_nfgds);
    
    //--- pion candidate truth variables -------
    AddVarF(output(),selpi_truemom, "");              // true pion momentum
    AddVar4VF(output(),selpi_truedir, ""); // true pion direction
    AddVarI(output(),selpi_pdg,"");
    
    // --- pion candidate recon variables -----
    AddToyVarI(output(),selpi_NDOF,      "");
    AddToyVarF(output(),selpi_Chi2,      "");
    AddToyVarF(output(),selpi_mom,      "");
    AddVar3VF(output(),selpi_dir, "");
    AddVarVI(output(),selpi_tpc_nhits,        "", selpi_ntpcs);
    AddVarVF(output(), selpi_tpc_charge,"", selpi_ntpcs);
    AddVar4VF(output(),selpi_endpos, "");
    AddVarVI(output(),selpi_fgd_det, "" , selpi_nfgds);
    
}

void numuCC1P1PiAnalysis::FillMicroTrees(bool addBase)
{
    // Fill variables from numuCCAnalysis
    if (addBase) _numuCCAnalysis->FillMicroTrees(addBase);
    
    if (box().ProtonCandidate) {
        //true variables
        if(  box().ProtonCandidate->TrueTrack ) {
            output().FillVar(selp_truemom,         box().ProtonCandidate->TrueTrack->Momentum);
            output().FillVectorVarFromArray(selp_truedir,     box().ProtonCandidate->TrueTrack->Direction,   3);
            output().FillVar(selp_pdg, box().ProtonCandidate->TrueTrack->PDG);
        }
        
        //Fill TPC Info
        for (Int_t subdet = 0; subdet<3; subdet++) {
            if (!SubDetId::GetDetectorUsed(box().ProtonCandidate->Detector, static_cast<SubDetId::SubDetEnum >(subdet+2))) continue;
            AnaTpcTrack* TPCSegment = static_cast<AnaTpcTrack*>(anaUtils::GetSegmentInDet( *box().ProtonCandidate,static_cast<SubDetId::SubDetEnum >(subdet+2)));
            if (!TPCSegment) continue;
            
            output().FillVectorVar(selp_tpc_nhits,   TPCSegment->NHits);
            output().FillVectorVar(selp_tpc_charge, TPCSegment->Charge);
            //important to have this:
            output().IncrementCounterForVar(selp_tpc_nhits);
        }
        //Fill FGD Info
        for(Int_t subdet = 0; subdet<2; subdet++){
            if (!SubDetId::GetDetectorUsed(box().HMNtrack->Detector, static_cast<SubDetId::SubDetEnum >(subdet))) continue;
            AnaFgdTrack* FGDSegment = static_cast<AnaFgdTrack*>(anaUtils::GetSegmentInDet( *box().HMNtrack,static_cast<SubDetId::SubDetEnum >(subdet)));
            if (!FGDSegment) continue;
            output().FillVectorVar(selp_fgd_det, subdet);
            output().IncrementCounterForVar(selp_fgd_det);
            
        }
        //basic kinematic variables that wont be changed by systematics propagation
        output().FillVectorVarFromArray(selp_endpos, box().ProtonCandidate->PositionEnd, 4);
        output().FillVectorVarFromArray(selp_dir,    box().ProtonCandidate->DirectionStart, 3);
    }
    
    if (box().PionCandidate) {
        //true variables
        if(  box().PionCandidate->TrueTrack ) {
            output().FillVar(selpi_truemom,         box().PionCandidate->TrueTrack->Momentum);
            output().FillVectorVarFromArray(selpi_truedir,     box().PionCandidate->TrueTrack->Direction,   3);
            output().FillVar(selpi_pdg,         box().PionCandidate->TrueTrack->PDG);
        }
        
        //Fill TPC Info
        for (Int_t subdet = 0; subdet<3; subdet++) {
            if (!SubDetId::GetDetectorUsed(box().PionCandidate->Detector, static_cast<SubDetId::SubDetEnum >(subdet+2))) continue;
            AnaTpcTrack* TPCSegment = static_cast<AnaTpcTrack*>(anaUtils::GetSegmentInDet( *box().PionCandidate,static_cast<SubDetId::SubDetEnum >(subdet+2)));
            if (!TPCSegment) continue;
            
            output().FillVectorVar(selpi_tpc_nhits, TPCSegment->NHits);
            output().FillVectorVar(selpi_tpc_charge, TPCSegment->Charge);
            //important to have this:
            output().IncrementCounterForVar(selpi_tpc_nhits);
        }
        //Fill FGD Info
        for(Int_t subdet = 0; subdet<2; subdet++){
            if (!SubDetId::GetDetectorUsed(box().HMNtrack->Detector, static_cast<SubDetId::SubDetEnum >(subdet))) continue;
            AnaFgdTrack* FGDSegment = static_cast<AnaFgdTrack*>(anaUtils::GetSegmentInDet( *box().HMNtrack,static_cast<SubDetId::SubDetEnum >(subdet)));
            if (!FGDSegment) continue;
            output().FillVectorVar(selpi_fgd_det, subdet);
            output().IncrementCounterForVar(selpi_fgd_det);
        }
        
        //basic kinematic variables that wont be changed by systematics propagation
        output().FillVectorVarFromArray(selpi_endpos, box().PionCandidate->PositionEnd, 4);
        output().FillVectorVarFromArray(selpi_dir,    box().PionCandidate->DirectionStart, 3);
    }
}

void numuCC1P1PiAnalysis::FillToyVarsInMicroTrees(bool addBase)
{
    // Variables from the numuCCAnalysis analysis (including the ones in baseAnalysis by default, otherwise addBase should be false
    if (addBase) _numuCCAnalysis->FillToyVarsInMicroTrees(addBase);
    
    if (box().ProtonCandidate) {
        AnaTrack* ProtonCandidate = static_cast<AnaTrack*>(box().ProtonCandidate);
        //basic kinematic vars
        output().FillToyVar(selp_mom,  ProtonCandidate->Momentum);
        output().FillToyVar(selp_NDOF,  ProtonCandidate->NDOF);
        output().FillToyVar(selp_Chi2,  ProtonCandidate->Chi2);
    }
    
    if (box().PionCandidate) {
        AnaTrack* PionCandidate = static_cast<AnaTrack*>(box().PionCandidate);
        //basic kinematic vars
        output().FillToyVar(selpi_mom,  PionCandidate->Momentum);
        output().FillToyVar(selpi_NDOF,  PionCandidate->NDOF);
        output().FillToyVar(selpi_Chi2,  PionCandidate->Chi2);
    }
}

//========================================================================================
//========================================================================================
void numuCC1P1PiAnalysis::InitializeConfiguration()
{
    // Use the same event for the numuCCAnalysis
    _numuCCAnalysis->SetEvent(_event);
    _numuCCAnalysis->InitializeConfiguration();
}

void numuCC1P1PiAnalysis::DefineConfigurations()
{
    // Same configurations as for numuCC
    _numuCCAnalysis->DefineConfigurations();
}

void numuCC1P1PiAnalysis::DefineCorrections()
{
    _numuCCAnalysis->DefineCorrections();
}

void numuCC1P1PiAnalysis::DefineSystematics()
{
    _numuCCAnalysis->DefineSystematics();
}

void numuCC1P1PiAnalysis::DefineTruthTree()
{
    // Variables from baseAnalysis (run, event, ...)
    _numuCCAnalysis->DefineTruthTree();
}

void numuCC1P1PiAnalysis::FillTruthTree(const AnaTrueVertex& vtx)
{
    // Fill the numuCC variables
    //enabling it makes the file output size smaller!!
    _numuCCAnalysis->FillTruthTree(vtx);
}

bool numuCC1P1PiAnalysis::CheckFillTruthTree(const AnaTrueVertex& vtx)
{
    return _numuCCAnalysis->CheckFillTruthTree(vtx);
}

bool numuCC1P1PiAnalysis::CheckFillRooTracker(const AnaTrueVertex& vtx)
{
    return _numuCCAnalysis->CheckFillRooTracker(vtx);
}

void numuCC1P1PiAnalysis::InitializeToy()
{
    // Delete the box and create a new one
    if (_cc1P1Pi_box) delete _cc1P1Pi_box;
    _cc1P1Pi_box = new AnaBoxCC1P1Pi();
    
    // Use the same box for the numuCCAnalysis
    _numuCCAnalysis->SetBox(_cc1P1Pi_box);
    
    // Use the same event for the numuCCAnalysis
    _numuCCAnalysis->SetEvent(_event);
}

void numuCC1P1PiAnalysis::FinalizeToy()
{
    _numuCCAnalysis->FinalizeToy();
}
